﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using Sunny.Lib;
using System.Xml;
using System.Xml.Linq;

namespace Sunny.Lib
{
    public class CustomerSection : ConfigurationSection
    {
        [ConfigurationProperty("recordlist")]
        public CustomerSectionRecords RecordList
        {
            get { return this["recordlist"] as CustomerSectionRecords; }
            set { this["recordlist"] = value; }
        }
    }
    public class CustomerSectionRecords : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new CustomerSectionRecord();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return (element as CustomerSectionRecord).Key;
        }

        public new CustomerSectionRecord this[string name]
        {
            get
            {
                return BaseGet(name) as CustomerSectionRecord;
            }
        }

        public new CustomerSectionRecord this[int index]
        {
            get
            {
                return BaseGet(index) as CustomerSectionRecord;
            }
        }

        protected override string ElementName
        {
            get
            {
                return ConfigurationSectionConst.ElementNameField;
            }
        }

        public override ConfigurationElementCollectionType CollectionType
        {
            get
            {
                return ConfigurationElementCollectionType.BasicMap;
            }
        }

        public void Add(CustomerSectionRecord element)
        {
            base.BaseAdd(element);
        }
    }
    public class CustomerSectionRecord : ConfigurationElement
    {
        [ConfigurationProperty(ConfigurationSectionConst.NameField, DefaultValue = "")]
        public string Key
        {
            get { return this[ConfigurationSectionConst.NameField] as string; }
            set { this[ConfigurationSectionConst.NameField] = value; }
        }

        [ConfigurationProperty(ConfigurationSectionConst.ValueField, DefaultValue = "")]
        public string Value
        {
            get { return this[ConfigurationSectionConst.ValueField] as string; }
            set { this[ConfigurationSectionConst.ValueField] = value; }
        }
    }

    public class CustomerConfigurationSectionHandler<T> : IConfigurationSectionHandler
        where T : new()
    {
        public object Create(object parent, object configContext, XmlNode section)
        {
            T o = new T();

            XmlNode addParentNode = section;
            while ((addParentNode.FirstChild.Name != ConfigurationSectionConst.ElementNameField) && addParentNode.FirstChild != null)
            {
                addParentNode = addParentNode.FirstChild;
            }

            foreach (XmlNode child in addParentNode.ChildNodes)
            {
                if (child.NodeType == XmlNodeType.Element)
                {
                    string name = child.Attributes[ConfigurationSectionConst.NameField].Value;
                    string value = child.Attributes[ConfigurationSectionConst.ValueField].Value;
                    ReflectionHelper.SetPropertyValue<T>(o, name, value);
                }
            }

            return o;
        }

        public static T GetConfigurationObject(string sectionGroupName, string sectionName)
        {
            T o = (T)ConfigurationHelper.GetConfigaration(string.Format("{0}/{1}", sectionGroupName, sectionName));
            return o;
        }

        public static void SaveConfigurationObject(T sectionData, string typeInfo, string sectionGroupName, string sectionName)
        {
            //ExeConfigurationFileMap file = new ExeConfigurationFileMap() { ExeConfigFilename = "TestHelper.exe.config" };
            //Configuration config = ConfigurationManager.OpenMappedExeConfiguration(file, ConfigurationUserLevel.None);
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            T o = CustomerConfigurationSectionHandler<T>.GetConfigurationObject(sectionGroupName, sectionName);

            // Update(remove and add again)
            if (null != o)
            {
                config.SectionGroups[sectionGroupName].Sections.Remove(sectionName);
            }

            // Insert
            CustomerSection setionRecord = new CustomerSection();
            setionRecord.SectionInformation.Type = typeInfo;
            Dictionary<string, object> nameValues = ReflectionHelper.GetPropertiesKeyValuePairs<T>(sectionData, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
            foreach (var nameValue in nameValues)
            {
                CustomerSectionRecord record = new CustomerSectionRecord() { Key = nameValue.Key, Value = nameValue.Value.ToString() };
                setionRecord.RecordList.Add(record);
            }
            config.SectionGroups[sectionGroupName].Sections.Add(sectionName, setionRecord);


            config.Save();
        }

        public static string[] GetConfigurationSectionNames(string sectionGroupName = null)
        {
            string sectionPaths = string.Empty;

            StringBuilder sb = new StringBuilder();
            char[] split = new char[] { '|' };
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            if (string.IsNullOrEmpty(sectionGroupName))
            {
                foreach (var group in config.SectionGroups)
                {
                    var sectionGroup = config.SectionGroups[sectionGroupName];
                    //string groupName = sectionGroup.SectionGroupName;
                    foreach (var section in sectionGroup.Sections)
                    {
                        string sectionName = ((System.Configuration.ConfigurationSection)(section)).SectionInformation.Name;
                        //sb.AppendFormat("{0}/{1}|", groupName, sectionName);
                        sb.AppendFormat("{0}|", sectionName);
                    }
                }
            }
            else
            {
                var sectionGroup = config.SectionGroups[sectionGroupName];
                //string groupName = sectionGroup.SectionGroupName;
                foreach (var section in sectionGroup.Sections)
                {
                    string sectionName = ((System.Configuration.ConfigurationSection)(section)).SectionInformation.Name;
                    //sb.AppendFormat("{0}/{1}|", groupName, sectionName);
                    sb.AppendFormat("{0}|", sectionName);
                }
            }
            sectionPaths = sb.ToString();
            if (!string.IsNullOrEmpty(sectionPaths))
            {
                sectionPaths = sectionPaths.Trim('|');
                return sectionPaths.Split(split);
            }

            return null;
        }
    }
    public class HttpRequestConfigurationSectionHandler : CustomerConfigurationSectionHandler<HttpRequestConfiguration>
    {
        public const string GroupName = "httpRequestConfigurationGroup";

        private static string typeAndAssamblyName = string.Empty;
        public static string TypeAndAssamblyName
        {
            get
            {
                if (string.IsNullOrEmpty(typeAndAssamblyName))
                {
                    typeAndAssamblyName = string.Format("{0},{1}", typeof(HttpRequestConfigurationSectionHandler).FullName, typeof(HttpRequestConfigurationSectionHandler).Assembly.FullName);
                }
                return typeAndAssamblyName;
            }
        }
    }
    public class AlipayUnionPaySignConfigurationSectionHandler : CustomerConfigurationSectionHandler<AlipayUnionPaySignConfiguration>
    {
        public const string GroupName = "mySectionGroup";
        private static string typeAndAssamblyName = string.Empty;
        public static string TypeAndAssamblyName
        {
            get
            {
                if (string.IsNullOrEmpty(typeAndAssamblyName))
                {
                    typeAndAssamblyName = string.Format("{0},{1}", typeof(AlipayUnionPaySignConfigurationSectionHandler).FullName, typeof(AlipayUnionPaySignConfigurationSectionHandler).Assembly.FullName);
                }
                return typeAndAssamblyName;
            }
        }
    }
    public class TestCertConfigurationSectionHandler : CustomerConfigurationSectionHandler<TestCertConfiguration>
    {
        public const string GroupName = "mySectionGroup";
        private static string typeAndAssamblyName = string.Empty;
        public static string TypeAndAssamblyName
        {
            get
            {
                if (string.IsNullOrEmpty(typeAndAssamblyName))
                {
                    typeAndAssamblyName = string.Format("{0},{1}", typeof(TestCertConfigurationSectionHandler).FullName, typeof(TestCertConfigurationSectionHandler).Assembly.FullName);
                }
                return typeAndAssamblyName;
            }
        }
    }
    //
    // 1.Here add a new section handler:TestSectionHandler
    //
    public class TestSectionHandler : CustomerConfigurationSectionHandler<TestCertConfiguration>
    {
        public const string GroupName = "TestGroup";

        private static string typeAndAssamblyName = string.Empty;
        public static string TypeAndAssamblyName
        {
            get
            {
                if (string.IsNullOrEmpty(typeAndAssamblyName))
                {
                    typeAndAssamblyName = string.Format("{0},{1}", typeof(TestSectionHandler).FullName, typeof(TestSectionHandler).Assembly.FullName);
                }
                return typeAndAssamblyName;
            }
        }
    }

    public class HttpRequestConfiguration
    {
        public RequestMethodType RequestMethod { get; set; }
        public string RequestUrl { get; set; }
        public string RequestParameters { get; set; }
        public string RequestContentType { get; set; }
        public string CertificateInfo { get; set; }
        public string CertificatePassword { get; set; }
        public string CredentialUserName { get; set; }
        public string CredentialPassword { get; set; }
        public string CredentialDomain { get; set; }
    }
    public class AlipayUnionPaySignConfiguration
    {
        public string PrivateKey { get; set; }
    }
    public class TestCertConfiguration
    {
        public string SendSideCertPath { get; set; }
        public string SendSideCertPassword { get; set; }
        public string RecieveSideCertPath { get; set; }
        public string RecieveCertPassword { get; set; }
        public Algorithm SignAlgorithm { get; set; }
        public string SignEncoding { get; set; }
        public Algorithm AsymmetryAlgorithm { get; set; }
        public string AsymmetryEncoding { get; set; }
        public Algorithm SymmetryAlgorithm { get; set; }
        public string SymmetryEncoding { get; set; }
        public string Key { get; set; }
        public string Iv { get; set; }
    }
    //
    // 2.Here add a new configuration class:TestConfiguration    
    //
    public class TestConfiguration
    {
        public string Test1 { get; set; }
        public string Test2 { get; set; }
        public string Test3 { get; set; }
    }

    public class ConfigurationHelper
    {
        private static string defaultXml;
        public static string DefaultXml
        {
            get
            {
                if (string.IsNullOrEmpty(defaultXml))
                {
                    defaultXml = GetAppSettingsConfigrationByName("defaultXml");
                }
                return defaultXml;
            }
        }

        private static string rootXml;
        public static string RootXml
        {
            get
            {
                if (string.IsNullOrEmpty(rootXml))
                {
                    rootXml = GetAppSettingsConfigrationByName("RootXml");
                }
                return rootXml;
            }
        }

        private static string tabTemplete;
        public static string TabTemplete
        {
            get
            {
                if (string.IsNullOrEmpty(tabTemplete))
                {
                    tabTemplete = GetAppSettingsConfigrationByName("TabTemplete");
                }
                return tabTemplete;
            }
        }

        private static string canEidtRootXmlFlag = string.Empty;
        private static bool canEidtRootXml = false;
        public static bool CanEidtRootXml
        {
            get
            {
                if (string.IsNullOrEmpty(canEidtRootXmlFlag))
                {
                    canEidtRootXmlFlag = GetAppSettingsConfigrationByName("CanEidtRootXml");
                    bool.TryParse(canEidtRootXmlFlag, out canEidtRootXml);
                }
                return canEidtRootXml;
            }
        }

        private static string connectionString;
        public static string ConnectionString
        {
            get
            {
                if (string.IsNullOrEmpty(connectionString))
                {
                    connectionString = GetAppSettingsConfigrationByName("xmlDbCon");
                }
                return connectionString;
            }
        }

        private static string dataBaseName;
        public static string DataBaseName
        {
            get
            {
                if (string.IsNullOrEmpty(dataBaseName))
                {
                    dataBaseName = GetAppSettingsConfigrationByName("xmlDbName");
                }
                return dataBaseName;
            }
        }

        public static string GetAppSettingsConfigrationByName(string configrationName)
        {
            string configrationValue = string.Empty;

            try
            {
                configrationValue = System.Configuration.ConfigurationSettings.AppSettings[configrationName].ToString().Trim();
            }
            catch (Exception ex)
            {
                Logger.LogEvent(ex.Message, EventLevel.Error, ex.StackTrace);
            }

            return configrationValue;
        }

        public static string GetConnectionStrings()
        {
            string connectionString = string.Empty;

            object connection = GetConfigaration("connectionStrings");
            if (connection != null)
            {
                ConnectionStringsSection connectionSection = connection as ConnectionStringsSection;
                if (connectionSection != null)
                {
                    if (connectionSection.ConnectionStrings.Count > 1)
                    {
                        connectionString = connectionSection.ConnectionStrings[1].ConnectionString;
                    }
                }
            }

            return connectionString;
        }

        public static object GetConfigaration(string sectionPath)
        {
            try
            {
                return System.Configuration.ConfigurationSettings.GetConfig(sectionPath);
            }
            catch (Exception ex)
            {
                return null;
            }
        }
    }

    public class ConfigurationSectionConst
    {
        public const string ElementNameField = "add";
        public const string NameField = "key";
        public const string ValueField = "value";
    }
}
